// Copyright (C) CompatibL Technologies LLC. All rights reserved.
// This code contains valuable trade secrets and may be used, copied,
// stored, or distributed only in accordance with a written license
// agreement and with the inclusion of this copyright notice. 

#region File Info
// File       : ChordCreatorControl.cs
// Description: ChordCreatorControl.ChordCreatorControl user control implementation.
// Package    : ChordCreatorControl 
//
#endregion

using System; 
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ChordCreator.Model;
using ChordCreator.Services;
using ChordCreator.Services.ConfigurationServices;

namespace ChordCreator
{
    /// <summary>
    /// Summary description for ChordCreatorControl.
    /// </summary>
    public partial class ChordCreatorControl : UserControl
    {
        private Scale scale_;
        private readonly ScalesPredefiner scalesPredefiner_;

        /// <summary>
        /// Initializes a new instance of the <see cref="ChordCreatorControl"/> user control.
        /// </summary>
        public ChordCreatorControl()
        {
            InitializeComponent();
            scalesPredefiner_ = new ScalesPredefiner();
            predefinedScales_.Items.AddRange(scalesPredefiner_.GetScaleNames());
            tonicCombo_.Items.AddRange(XmlConfiguration.Instance.Handlerer.ScaleDisplaying.Select(x => x.DisplayedTonic).ToArray());
        }

        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            scale_ = new Scale(tonicCombo_.SelectedItem.ToString());
            CurrentConfiguration.Instance.SetScale(XmlConfiguration.Instance.Handlerer.ScaleDisplaying.Where(x => x.Tonic == scale_.Tonic).Select(x => x.ScalePresentation).Single().ToArray(), scale_.Tonic);
            FillChromatic(scale_);
        }

        private void FillChromatic(Scale scale)
        {
            chromaticBox_.Items.Clear();
            foreach (var note in scale.GenerateChromaticScale())
            {
                chromaticBox_.Items.Add(CurrentConfiguration.Instance.GetNotePresentation(note), false);
            }
        }

        private void FillScale()
        {
            scaleBox_.Items.Clear();
            scaleBox_.Items.AddRange(scale_.GetConcreteScale());
        }

        private void CreateResult(Scale firstChordNotes, ChordBase<ScaleNote> scale)
        {
            ChordResolver chordResolver = new ChordResolver(scale_);
            stringsControl1.ShowNotes(firstChordNotes.GetConcreteScale().Select(x => x).ToArray());
            List<ChordScale> chordNotes;

            string result = chordResolver.FormOutput(scale.Notes.ToList(), out chordNotes);
            FillChordsOnFrets(chordNotes);
            outputBox_.Text += Environment.NewLine;
            outputBox_.Text += "-----------------------------";
            outputBox_.Text += Environment.NewLine;
            outputBox_.Text += DateTime.Now;
            outputBox_.Text += Environment.NewLine;
            StringBuilder scaleOutput = new StringBuilder();
            CurrentConfiguration configuration = CurrentConfiguration.Instance;
            foreach (ScaleNote scaleNote in scale_.GetConcreteScale())
            {
                scaleOutput.Append(string.Format("{0}, ", configuration.GetNotePresentation(scaleNote.Note)));
            }
            outputBox_.Text += string.Format("Scale is: {0}, ", scaleOutput.ToString().Trim(',', ' '));
            outputBox_.Text += Environment.NewLine;
            StringBuilder chordsOutput = new StringBuilder();
            foreach (var chordNote in firstChordNotes.GetConcreteScale())
            {
                chordsOutput.Append(string.Format("{0}, ", configuration.GetNotePresentation(chordNote.Note)));
            }
            outputBox_.Text += string.Format("Chord is: {0}, ", chordsOutput.ToString().Trim(',', ' '));
            outputBox_.Text += Environment.NewLine;
            outputBox_.Text += Environment.NewLine;
            outputBox_.Text += result;
        }

        private void FillChordsOnFrets(IList<ChordScale> chords)
        {
            chordList_.Items.Clear();
            for (int i=0; i< chords.Count; i++)
            {
                chordList_.Items.Add(chords[i]);
            }
            if (chords.Count != 0)
                chordList_.SelectedIndex = 0;
        }

        private void button3_Click(object sender, EventArgs e)
        {
            outputBox_.Text = "";
        }


        private void PositioningListCompleted()
        {
            List<ScaleNote> firstChordNotes = new List<ScaleNote>();
            foreach (ListViewItem note in positioningList_.Items)
            {
                firstChordNotes.Add((ScaleNote) note.Tag);
            }
            Scale newScale = new Scale(scale_.Tonic);
            newScale.SetConreteScale(firstChordNotes.Select(x => x.Note).ToList());
            ChordScale chordScale = new ChordScale(firstChordNotes.ToArray());
            chordArchitectorControl_.Initialize(chordScale);
            chordArchitectorControl_.ChordArchitectureChanged += chordArchitectorControl__ChordArchitectureChanged;
            CreateResult(newScale, chordScale);
        }

        void chordArchitectorControl__ChordArchitectureChanged(object sender, View.StringsFunctionality.ChordArchitector.ChordArchChangedEventArgs e)
        {
            stringsControl1.SetLinesFormat(e.Notes);
        }

        private void scaleBox__SelectedIndexChanged(object sender, EventArgs e)
        {
            ScaleBoxCompleted();
        }

        private void ScaleBoxCompleted()
        {
            List<ScaleNote> firstChordNotes = scaleBox_.CheckedItems.OfType<ScaleNote>().ToList();
            positioningList_.Items.Clear();
            foreach (var note in firstChordNotes)
            {
                positioningList_.Items.Add(note.ToString()).Tag = note;
            }
        }

        private void chromaticBox__SelectedIndexChanged(object sender, EventArgs e)
        {
            ChromaticBoxCompleted();
        }

        private void ChromaticBoxCompleted()
        {
            List<string> notes = chromaticBox_.CheckedItems.OfType<string>().ToList();

            scale_.SetConreteScale(CurrentConfiguration.Instance.GetNotesFromPresentations(notes));
            FillScale();
        }

        private void chromaticBox__SelectedValueChanged(object sender, EventArgs e)
        {
            ChromaticBoxCompleted();
        }

        private void scaleBox__SelectedValueChanged(object sender, EventArgs e)
        {
            ScaleBoxCompleted();
        }

        private void chromaticBox__MouseUp(object sender, MouseEventArgs e)
        {
            ChromaticBoxCompleted();
        }

        private void scaleBox__MouseUp(object sender, MouseEventArgs e)
        {
            ScaleBoxCompleted();
        }

        private void button1_Click_1(object sender, EventArgs e)
        {
            PositioningListCompleted();
        }


        private void predefinedScales__MouseDown(object sender, MouseEventArgs e)
        {
            if (predefinedScales_.SelectedItem != null)
            {
                int[] scale = scalesPredefiner_.GetDegreesByScale(predefinedScales_.SelectedItem.ToString());


                if (chromaticBox_.Items.Count == 0)
                {
                    return;
                }
                for (int i = 0; i < 12; i++)
                {
                    chromaticBox_.SetItemChecked(i, false);
                }
                foreach (int i in scale)
                {
                    chromaticBox_.SetItemChecked(i-1, true);
                }
                ChromaticBoxCompleted();
            }
        }

        private void chordList__SelectedIndexChanged(object sender, EventArgs e)
        {
            ChordScale chord = (ChordScale)chordList_.SelectedItem;
            stringsControl1.DrawHUD();
            stringsControl1.ShowNotes(chord.Notes);
        }

        private void cpyToClipBoardButton__Click(object sender, EventArgs e)
        {
            Clipboard.SetText(outputBox_.Text);
        }
    }
}
